package cn.lijiajia3515.cairo.auth.modules;

import cn.lijiajia3515.cairo.auth.framework.security.CairoAuthAccount;
import cn.lijiajia3515.cairo.auth.framework.security.oauth2.CairoOAuth2User;
import cn.lijiajia3515.cairo.core.business.AuthBusiness;
import cn.lijiajia3515.cairo.core.business.DefaultBusiness;
import cn.lijiajia3515.cairo.core.exception.BusinessException;
import cn.lijiajia3515.cairo.domain.CairoAccount;
import cn.lijiajia3515.cairo.security.authentication.CairoAuthentication;
import cn.lijiajia3515.cairo.security.oauth2.jwt.CairoJwtPrincipal;
import cn.lijiajia3515.cairo.security.oauth2.resource.server.authentication.CairoJwtAuthenticationToken;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.security.PermitAll;
import java.util.Collection;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api")
public class IndexApi {

	@GetMapping("/authentication")
	@PreAuthorize("hasAuthority('account')")
	public cn.lijiajia3515.cairo.auth.CairoAuthentication authentication(Authentication authentication) {
		if (authentication instanceof CairoAuthentication) {
			// self
			return build((CairoAuthentication) authentication, authentication.getAuthorities());
		} else if (authentication.getPrincipal() instanceof CairoAuthAccount) {
			// form login
			return build((CairoAuthAccount) authentication.getPrincipal(), authentication.getAuthorities());
		} else if (authentication.getPrincipal() instanceof CairoOAuth2User) {
			// oauth2 login
			return build((CairoOAuth2User) authentication.getPrincipal(), authentication.getAuthorities());
		} else if (authentication instanceof CairoJwtAuthenticationToken) {
			// oauth2 resource jwt
			return build((((CairoJwtAuthenticationToken) authentication).getPrincipal().getAccount()), authentication.getAuthorities());
		} else {
			throw new BusinessException("凭证不可解析, 请联系管理员", AuthBusiness.Bad);
		}
	}

	@GetMapping(value = "/account")
	@PreAuthorize("hasAuthority('account')")
	public CairoAccount userinfo(@AuthenticationPrincipal Object principal) {
		if (principal instanceof CairoJwtPrincipal) {
			return ((CairoJwtPrincipal) principal).getAccount();
		} else if (principal instanceof CairoAuthAccount) {
			return (CairoAccount) principal;
		} else {
			throw new BusinessException("凭证不可解析, 请联系管理员", AuthBusiness.Bad);
		}
	}

	cn.lijiajia3515.cairo.auth.CairoAuthentication build(CairoAccount account, Collection<? extends GrantedAuthority> authorities) {
		return cn.lijiajia3515.cairo.auth.CairoAuthentication.builder()
			.id(account.getId())
			.nickname(account.getNickname())
			.email(account.getEmail())
			.phoneNumber(account.getPhoneNumber())

			.nickname(account.getNickname())
			.avatarUrl(account.getAvatarUrl())
			.departments(account.getDepartments())
			.roles(account.getRoles())
			.authorities(authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()))
			.build();
	}

}
